using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using LFromeWork;
using UnityEngine;

namespace LFromeWork
{
    public class AssetBundleRefEntity
    {
        /// <summary>
        /// 资源包路径
        /// </summary>
        public string AssetBundlePath;

        /// <summary>
        /// 加载资源包完毕
        /// </summary>
        public Action<AssetBundle> OnLoadAssetBundleComplete;

        /// <summary>
        /// 资源包创建请求
        /// </summary>
        public AssetBundleCreateRequest CurrAssetBundleCreateRequest { get; private set; }

        /// <summary>
        /// 关联目标
        /// </summary>
        public AssetBundle Target;

        /// <summary>
        /// 释放时间
        /// </summary>
        public float ReleaseTime { get; private set; }

        /// <summary>
        /// 引用计数
        /// </summary>
        public int ReferenceCount { get; private set; }

        /// <summary>
        /// 刷新最后使用时间
        /// </summary>
        public void RefreshReleaseTime()
        {
            ReleaseTime = Time.time + GameLaunch.ParamsSettings.PoolReleaseAssetBundleInterval;
        }

        /// <summary>
        /// 引用计数+1
        /// </summary>
        public void ReferenceAdd()
        {
            ReferenceCount++;
        }

        /// <summary>
        /// 引用计数-1
        /// </summary>
        public void ReferenceRemove()
        {
            ReferenceCount--;
            RefreshReleaseTime();
            if (ReferenceCount < 0)
            {
                GameLaunch.LogError("AB引用计数出错， ReferenceCount==" + ReferenceCount);
            }
        }

        /// <summary>
        /// 对象是否可以释放
        /// </summary>
        /// <returns></returns>
        public bool GetCanRelease()
        {
            return ReferenceCount == 0 && Time.time >= ReleaseTime && Target != null;
        }

        /// <summary>
        /// 创建资源实体
        /// </summary>
        /// <param name="path"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static AssetBundleRefEntity Create(string path)
        {
            AssetBundleRefEntity assetBundleEntity = GameLaunch.Pool.CoPool.Dequeue<AssetBundleRefEntity>();
            assetBundleEntity.AssetBundlePath = path;

            return assetBundleEntity;
        }

        #region LoadAssetBundle 加载资源包

        public void LoadAssetBundleAsync()
        {
            //检查文件在可写区是否存在
            string filePath = string.Format("{0}/{1}", Application.persistentDataPath, AssetBundlePath);
            bool fileExit = File.Exists(filePath);
            
            //如果可写区不存在，去判断streammingAsset 是否存在 
            if (!fileExit)
            {
                filePath = string.Format("{0}/{1}/{2}", Application.streamingAssetsPath,LFConstDefine.AssetBundles, AssetBundlePath);
                fileExit = File.Exists(filePath);
            }
            
            if (fileExit)
            {
                //可写区加载, 需要解密
                byte[] buffer = IOUtil.GetFileBuffer(filePath);
                CurrAssetBundleCreateRequest = AssetBundle.LoadFromMemoryAsync(buffer);
            }
            else
            {
                GameLaunch.LogError("不存在 assetBundlePath:" + AssetBundlePath);
            }
        }

        #endregion

        #region UpdateAssetBundleCreateRequest 更新资源包请求

        /// <summary>
        /// 更新资源包请求
        /// </summary>
        public void UpdateAssetBundleCreateRequest()
        {
            if (CurrAssetBundleCreateRequest == null) return;
            if (CurrAssetBundleCreateRequest.isDone)
            {
                Target = CurrAssetBundleCreateRequest.assetBundle;
                if (Target == null)
                    GameLaunch.LogError("资源包加载失败 => " + AssetBundlePath);

                OnLoadAssetBundleComplete?.Invoke(Target);

                OnLoadAssetBundleComplete = null;
                CurrAssetBundleCreateRequest = null;
            }
        }

        #endregion

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Release()
        {
            Target.Unload(true);
            AssetBundlePath = null;
            Target = null;
            GameLaunch.Pool.CoPool.Enqueue(this);
        }
    }
}
